home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
mint104s.zoo
/
mint.src
/
memprot.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-08
|
32KB
|
1,148 lines
/*
* Copyright 1991,1992,1993 Atari Corporation.
* All rights reserved.
*/
/*
* page-table data structures
*
*
* The root pointer points to a list of pointers to top-level pointer tables.
*
* Each entry in a pointer table points to another pointer table or to
* a page table, or is a page descriptor.
*
* Since, initially, the logical address space is the physical address space,
* we only need to worry about 26MB plus 32K for I/O space.
*
* Since we want some pages to be supervisor-accessible, but we don't want
* a whole separate table for that, we use long-format descriptors.
*
* Initial memory map:
*
* 0 - membot: S (supervisor only)
* membot - memtop: P (protected TPA)
* memtop - phystop: G (screen)
* phystop - $00E00000: bus error
* $00E00000- $00E3FFFF: G (ROM)
* $00E40000- $00FF7FFF: bus error
* $00FF8000- $00FFFFFF: G (mostly S: I/O space, but that's done in hardware)
* $01000000- ramtop: P
* ramtop - $7FFFFFFF: G (A32/D32 VME, cacheable)
* $80000000- $FEFFFFFF: G (A32/D32 VME, non cacheable)
* $FFxxxxxx just like $00xxxxxx.
*
* Here's a final choice of layouts: IS=0, PS=13 (8K), TIA=4, TIB=4, TIC=4,
* TID=7. This lets us map out entire unused megabytes at level C, and gives
* us an 8K page size, which is the largest the '040 can deal with.
*
* This code implements 4+4+4+7, as follows:
*
* tbl_a
* 0 -> tbl_b0
* 1-7 -> Cacheable direct (VME) page descriptors
* 8-E -> Non-cacheable direct (VME) page descriptors
* F -> tbl_bf
*
* tbl_b0 table: 16 entries (assumes only 16MB of TT RAM)
* 0 -> tbl_c00 (16MB of ST RAM address space)
* 1 -> tbl_c01 (16MB of TT RAM address space)
* 2-F -> cacheable direct (VME) page descriptors
*
* tbl_bF table: 16 entries (deals with $FF mapping to $00)
* 0-E -> Non-cacheable direct (VME) page descriptors
* F -> tbl_c00 (16MB of ST RAM address space, repeated here as $FF)
*
* tbl_c00 table: ST RAM address space (example assuming 4MB ST RAM)
* 0-3 -> RAM page tables
* 4-D -> invalid
* E -> direct map, cache enable (ROM)
* F -> direct map, cache inhibit (I/O)
*
* For each 16MB containing any TT RAM, there's a tbl_c. Within those,
* for each MB that actually has TT RAM, there's another table, containing
* 128 RAM page tables. Where there isn't RAM, there are "global"
* pages, to let the hardware bus error or not as it sees fit.
*
* One RAM page table is allocated per megabyte of real RAM; each table has
* 128 entries, which is 8K per page. For a TT with 4MB ST RAM and 4MB TT RAM
* that's 8K in page tables. You can cut this down by not allocating page
* tables for which the entire megabyte is not accessible (i.e. it's all
* private memory and it's not YOUR private memory).
*
* You have one of these per process. When somebody loads into G or S memory
* or leaves it, you have to go through the page tables of every process
* updating S bits (for S) and DT (for G) bits.
*
* The top levels are small & easy so replicating them once per process
* doesn't really hurt us.
*
*/
#include "mint.h"
#if 0
#define MP_DEBUG(x) DEBUG(x)
#else
#define MP_DEBUG(x)
#endif
void *memset P_((void *s, int ucharfill, unsigned long size));
static void _dump_tree P_((long_desc tbl, int level));
extern int debug_level; /* see debug.c */
/*
* You can turn this whole module off, and the stuff in context.s,
* by setting no_mem_prot to 1.
*/
int no_mem_prot;
long page_table_size;
/*
* PMMU stuff
*/
#if 1
#define flush_pmmu(start, end) __asm("pflusha")
#else
/* in cpu.spp is a new "cpush" function that can selectively flush
* the cache
*/
#define flush_pmmu(start, len) cpush((void *)(start), (long)(len))
#endif
/*
* This is one global TC register that is copied into every process'
* context, even though it never changes. It's also used by the
* functions that dump page tables.
*/
tc_reg tc;
/* mint_top_* get used in mem.c also */
ulong mint_top_tt;
ulong mint_top_st;
int tt_mbytes; /* number of megabytds of TT RAM */
/*
* global_mode_table: one byte per page in the system. Initially all pages
* are set to "global" but then the TPA pages are set to "invalid" in
* init_mem. This has to be allocated and initialized in init_tables,
* when you know how much memory there is. You need a byte per page,
* from zero to the end of TT RAM, including the space between STRAM
* and TTRAM. That is, you need 16MB/pagesize plus (tt_mbytes/pagesize)
* bytes here.
*/
unsigned char *global_mode_table;
/*
* prototype descriptors; field u1 must be all ones, other u? are zero.
* This is just the first long of a full descriptor; the ".page_type" part
* of the union. These are initialized by init_tables.
*
* The proto_page_type table yields the value to stuff into the page_type
* field of a new process' page table. It is the "non-owner" mode for
* a page with the corresponding value in global_mode_table.
*/
page_type g_page;
page_type g_ci_page;
page_type s_page;
page_type readable_page;
page_type invalid_page;
page_type page_ptr;
page_type *proto_page_type[] =
{ &invalid_page, &g_page, &s_page, &readable_page, &invalid_page };
/* private global super private/read invalid */
/*
* Init_tables: called sometime in initialization. We set up some
* constants here, but that's all. The first new_proc call will set up the
* page table for the root process and switch it in; from then on, we're
* always under some process' control.
*
* The master page-mode table is initialized here, and some constants like
* the size needed for future page tables.
*
* One important constant initialized here is page_table_size, which is
* the amount of memory required per page table. new_proc allocates
* this much memory for each process' page table. This number will be
* 1K/megabyte plus page table overhead. There are TBL_PAGES_OFFS
* tables at TBL_SIZE_BYTES each before the main tables begin; then
* there is 1024 bytes per megabyte of memory being mapped.
*/
void
init_tables()
{
int n_megabytes;
long global_mode_table_size;
if (no_mem_prot) return;
TRACE(("init_tables"));
#define phys_top_tt (*(ulong *)0x5a4L)
if (phys_top_tt == 0x01000000L) mint_top_tt = 0;
else mint_top_tt = phys_top_tt;
#define phys_top_st (*(ulong *)0x42eL)
mint_top_st = phys_top_st;
if (mint_top_tt)
tt_mbytes = (int) ((mint_top_tt - 0x01000000L) / ONE_MEG);
else
tt_mbytes = 0;
n_megabytes = (int) ((mint_top_st / ONE_MEG) + tt_mbytes);
/*
* page table size: room for A table, B0 table, BF table, STRAM C
* table, one TTRAM C table per 16MB (or fraction) of TTRAM, and 1024
* bytes per megabyte.
*/
page_table_size = (4L * TBL_SIZE_BYTES) +
(((tt_mbytes+15L)/16L) * TBL_SIZE_BYTES) +
(n_megabytes*1024L);
global_mode_table_size = ((SIXTEEN_MEG / QUANTUM) +
(((ulong)tt_mbytes * ONE_MEG) / QUANTUM));
global_mode_table = kmalloc(global_mode_table_size);
assert(global_mode_table);
TRACELOW(("mint_top_st is $%lx; mint_top_tt is $%lx, n_megabytes is %d",
mint_top_st, mint_top_tt, n_megabytes));
TRACELOW(("page_table_size is %ld, global_mode_table_size %ld",
page_table_size,
global_mode_table_size));
g_page.limit = 0x7fff; /* set nonzero fields: disabled limit */
g_page.unused1 = 0x3f; /* ones in this reserved field */
g_page.unused2 = 0;
g_page.s = 0;
g_page.unused3 = 0;
g_page.ci = 0;
g_page.unused4 = 0;
g_page.m = 1; /* set m and u to 1 so CPU won't do writes */
g_page.u = 1;
g_page.wp = 0; /* not write-protected */
g_page.dt = 1; /* descriptor type 1: page descriptor */
g_ci_page = g_page;
g_ci_page.ci = 1;
readable_page = g_page; /* a page which is globally readable */
readable_page.wp = 1; /* but write protected */
s_page = g_page; /*